﻿using System;
using System.Collections;
using System.Text;

namespace uoLib.Authentication
{
    /// <summary>
    /// 拥有指定权限的角色对象
    /// </summary>
    /// <typeparam name="T">泛型 T （权限列表）必须是一个枚举。请见示例：<see cref="uoLib.Authentication.PowerItemExample"/></typeparam>
    public class PoweredMember<T> where T : IComparable, IConvertible, IFormattable
    {
        #region CONST
        private const string TTypeErr = "泛型 T （权限列表）必须是一个枚举！";
        private const string TBaseErr = "泛型 T （权限列表）所指定的枚举其基础类型必须是 long ！";
        private const string MinPowerErr = "参数必须大于 -1 ！";
        private const string PowerStringErr = "参数必须是由0、1构成的二进制字符串！";
        #endregion

        #region 属性
        private T _power;
        /// <summary>
        /// 获取当前对象的权限
        /// </summary>
        public T Power
        {
            get { return _power; }
            private set
            {
                Array values = Enum.GetValues(value.GetType());
                long tmpV = 0;
                string ArgumentExceptionMessage = "泛型 T （权限列表）的值必须是1或偶数，且不能重复！";
                for (int n = 0; n < values.Length; n++)
                {
                    tmpV = TtoInt64((T)values.GetValue(n));
                    if (tmpV < 0 || (tmpV % 2 != 0 && tmpV != 1)) { throw new ArgumentException(ArgumentExceptionMessage); }

                    for (int k = 0; k < n; k++)
                    {
                        if (tmpV == TtoInt64((T)values.GetValue(k)))
                        {
                            throw new ArgumentException(ArgumentExceptionMessage);
                        }
                    }
                }
                _power = value;
            }
        }
        /// <summary>
        /// 获取当前对象权限的二进制字符串形式
        /// </summary>
        public string PowerString { get { return Convert.ToString(TtoInt64(this.Power), 2); } }
        /// <summary>
        /// 获取当前对象权限的长整形形式
        /// </summary>
        public long PowerInt { get { return TtoInt64(this.Power); } }
        #endregion

        #region 构造函数
        /// <summary>
        /// 获取拥有指定权限的角色对象
        /// </summary>
        /// <param name="ownedPower">该角色拥有的权限。如：“<typeparamref name="T"/>.查看用户 | <typeparamref name="T"/>.查看设备”</param>
        public PoweredMember(T ownedPower)
        {
            if (!(ownedPower.GetType().IsEnum)) throw new ArgumentException(TTypeErr);
            if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int64)) { throw new ArgumentException(TBaseErr); }

            Power = ownedPower;
        }
        /// <summary>
        /// 获取拥有指定权限的角色对象
        /// </summary>
        /// <param name="ownedPower">该角色拥有的权限（标识，将被转换为二进制形式）</param>
        public PoweredMember(long ownedPower)
        {
            if (ownedPower < 0) { throw new ArgumentOutOfRangeException(MinPowerErr); }
            if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int64)) { throw new ArgumentException(TBaseErr); }

            T tmp = (T)Enum.Parse(typeof(T), ownedPower.ToString());
            this.Power = tmp;
        }
        /// <summary>
        /// 获取拥有指定权限的角色对象
        /// </summary>
        /// <param name="ownedPower">该角色拥有的权限（二进制如：“10000100000”）</param>
        public PoweredMember(string ownedPower)
        {
            if (string.IsNullOrEmpty(ownedPower) || ownedPower.Trim().Length == 0) throw new ArgumentNullException("ownedPower");
            if (ownedPower.Trim().Replace("0", "").Replace("1", "").Length != 0) throw new ArgumentOutOfRangeException(PowerStringErr);

            long p = Convert.ToInt64(ownedPower, 2);
            T tmp = (T)Enum.Parse(typeof(T), p.ToString());
            this.Power = tmp;
        }
        #endregion

        #region 方法
        /// <summary>
        /// 检查当前对象是否满足指定权限要求
        /// </summary>
        /// <param name="powerNeeded">需要满足的权限</param>
        /// <returns></returns>
        public bool Check(T powerNeeded)
        {
            //if (!Enum.IsDefined(typeof(T), powerNeeded))
            //    throw new ArgumentOutOfRangeException("powerNeeded", "枚举值 “" + powerNeeded.ToString() + "” 未定义！");

            if (powerNeeded.ToString() == "0") { return false; }

            long n = TtoInt64(powerNeeded);
            long myPower = TtoInt64(this.Power);

            //用户拥有的权限：  10110
            //操作需要的权限：  10010
            //& 操作    -------------
            //                  10010
            //        = 操作需要的权限
            return ((myPower & n) == n);
        }
        /// <summary>
        /// 将权限对象转化为长整形形式
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static long TtoInt64(T obj)
        {
            return long.Parse(((Enum)Enum.Parse(typeof(T), obj.ToString())).ToString("d"));
        }
        #endregion

        #region 重载
        /// <summary>
        /// 查看当前对象的权限详情
        /// </summary>
        /// <returns></returns>
        public new string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("角色权限");
            sb.AppendLine("-------------------------------------");
            sb.AppendLine("权限标识：" + TtoInt64(Power));
            sb.AppendLine("二进制字符串：" + this.PowerString);

            sb.AppendLine("权限详情：（" + this.Power + "）");
            Array powers = Enum.GetValues(typeof(T));
            IEnumerator ie = powers.GetEnumerator();
            T tmpP;
            while (ie.MoveNext())
            {
                tmpP = (T)Enum.Parse(typeof(T), ie.Current.ToString());
                if (Check(tmpP))
                {
                    sb.AppendLine("\t允许：" + tmpP.ToString());
                }
                else
                {
                    sb.AppendLine("\t禁止：" + tmpP.ToString());
                }
            }
            return sb.ToString();
        }
        #endregion
    }
}
